//**********************************************************************
//	Programmer	-	Sujal Bista
//	File Name	-	picture.cpp
//	Description	:	
//					general picture handler (some parts for HDR fromat
//					is from NVIDIA's HDR example)
//
//**********************************************************************


//Engine Header file
#ifndef _PICTURE_H
#define _PICTURE_H

//compile only once
#pragma once

//global data type
#include "global.h"
#include "graphicsBase.h"

//picture class
class picture
{
	public:

		enum IMAGE_FORMAT
		{
			IMAGE_FORMAT_RGB,
			IMAGE_FORMAT_RGBA,
			IMAGE_FORMAT_BGR,
			IMAGE_FORMAT_BGRA,
			IMAGE_FORMAT_RGB_FLOAT_32,
			IMAGE_FORMAT_RGBA_FLOAT_32,
			IMAGE_FORMAT_BGR_FLOAT_32,
			IMAGE_FORMAT_BGRA_FLOAT_32,
			IMAGE_FORMAT_BC1,	//DXT1
			IMAGE_FORMAT_BC2,	//DXT3
			IMAGE_FORMAT_BC3,	//DXT5
			IMAGE_FORMAT_BC4,
			IMAGE_FORMAT_BC5,
			IMAGE_FORMAT_BC6,
			IMAGE_FORMAT_BC7,
			IMAGE_FORMAT_DEPTH_8,
			IMAGE_FORMAT_DEPTH_16,
			IMAGE_FORMAT_DEPTH_24,
			IMAGE_FORMAT_DEPTH_32
		};

		unsigned int width;			//width of picture
		unsigned int height;		//height of picture
		unsigned int bytesPerPixel;	//number of bytes per pixel
		IMAGE_FORMAT format;		//rgba or bgra
		IMAGE_FORMAT internalFormat;	//internal format to save in video card
		float gamma;				//gamma value of picture default 1.0 for no gamma correction
		float exposure;				//a value of 1.0 in an image corresponds to <exposure> watts per steradian per m^2. 
									//defaults to 1.0
		unsigned char *data;		//pixel data

	private:

		//standard conversion from rgbe to float pixels 
		void rgbe2float(float &red, float &green, float &blue, unsigned char rgbe[4]);
		//simple read routine.  will not correctly handle run length encoding
		int RGBE_ReadPixels(std::ifstream &in, float *data, int numpixels);
		//reads and uncompresses the file
		int RGBE_ReadPixels_RLE(std::ifstream &in, float *data, int width,int height);

	public:
		
		//default constructor
		picture(void); 

		//constructor
		picture(
			const unsigned int &width,
			const unsigned int &height,
			unsigned int bytesPerPixel=4,
			IMAGE_FORMAT internalFormat=IMAGE_FORMAT_RGBA,
			IMAGE_FORMAT format=IMAGE_FORMAT_RGBA,
			float gamma=1.0f,
			float exposure=1.0f
			);
		
		//constructor
		picture(const picture &pic);

		//allocates memory for picture
		void allocate(
			const unsigned int &width,
			const unsigned int &height,
			unsigned int bytesPerPixel=4,
			IMAGE_FORMAT internalFormat=IMAGE_FORMAT_RGBA,
			IMAGE_FORMAT format=IMAGE_FORMAT_RGBA,
			float gamma=1.0f,
			float exposure=1.0f
			);

		//returns size of line in bytes
		//padded with 32 bit align
		unsigned int getLineSize(void) const;
		
		//flips an image horizontally
		void flipHorizontal(void);

		//flips an image vertically
		void flipVertically(void);

		//flips an image horizontally and vertically at the same time
		void flipHorizontalAndVertically(void);
		//inverts the color
		void invertColor(void);


		//inverts the color
		void BGR2RGB(void);

		//takes maximum of two images
		void bigger(const picture &pData);

		//add the image values
		void add(const picture &pData);

		//substract the image values
		void sub(const picture &pData);

		//max of two images
		void maximum(const picture &pData);

		//min of two images
		void minimum(const picture &pData);

		//replace one image content with another
		void replace(const picture &pData,const unsigned int &startX=0,const unsigned int &startY=0);

		//mixes two images
		void mix(const picture &pData,const float &startX=0.0f,const float &startY=0.0f,const float &multX=1.0f,const float &multY=1.0f);

		//mixes two images based on the position
		void mixPlus(const picture &pData,unsigned int *horizontalPos, unsigned int *verticalPos,const unsigned int &horizontalPosCount, const unsigned int &verticalPosCount,const unsigned int &startX=0,const unsigned int &startY=0);

		//adds padding on the image
		void addBoundary(unsigned int padSize);

		//removes boundary from the image
		void removeBoundary(unsigned int padSize);
		
		//converts depth map to visible map
		picture *depthToVisible(const unsigned int &width,const unsigned int &height,const double &nearPlane, const double &farPlane, float *data);

		//converts visible map to depth map
		picture *visibleToDepth(void);

		//load the bitmap form a file
		bool readBMP(const char *fileName);

		//load the HDR form a file
		bool readHDR(const char *fileName);

		//writes bitmap data to the file 
		bool writeBMP(const char *fileName, bool padded=true);

		//frees memory
		void clear(void);
		
		//destructor
		~picture();

};



#endif
